package springinpractice.ch4.r4_5.web;

import org.apache.commons.lang.StringUtils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Validator;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import springinpractice.ch4.r4_5.model.User;
import springinpractice.ch4.r4_5.service.DuplicateRegistrationException;
import springinpractice.ch4.r4_5.service.UserService;

/*
 * Author       :       Willie Wheeler and John Wheeler
 * Book         :       'Spring In Practice' [Book written by Willie Wheeler and John Wheeler]
 */

@Controller
@RequestMapping(value={"/register/form","/register/confirm"})
public class RegisterController {
	private static final String MA_USER = "user";

	private UserService userService;
	private Validator validator;

	@Autowired
	public void setUserService(UserService userService) {
		this.userService = userService;
	}

	@Autowired
	public void setValidator(Validator validator) {
		this.validator = validator;
	}

	@RequestMapping(method = RequestMethod.GET)
	public void form(Model model) {
		model.addAttribute(MA_USER, new User());
	}

	@RequestMapping(method = RequestMethod.POST)
	public String form(@ModelAttribute(MA_USER) User user, BindingResult result) {

		verifyBinding(result);
		validator.validate(user, result);

		try {
			userService.registerUserIfValid(user, !result.hasErrors());
		} catch (DuplicateRegistrationException dre) {
			if (dre.isUsernameTaken()) {
				result.rejectValue("username", "not.unique",
						new String[] { "Username" }, null);
			}
			if (dre.isEmailTaken()) {
				result.rejectValue("email", "not.unique");
			}
		}

		if (result.hasErrors()) {
			result.reject("form.problems");
			return "redirect:confirm.htm";
		}

		return "register/form";
	}

	
	public void confirm() {
	}

	@InitBinder
	public void initBinder(WebDataBinder binder) {
		binder.setAllowedFields(new String[] { "firstName", "lastName",
				"email", "username", "password", "passwordConfirmation" });
	}

	private void verifyBinding(BindingResult result) {
		String[] suppressedFields = result.getSuppressedFields();
		if (suppressedFields.length > 0) {
			throw new RuntimeException(
					"You've attempted to bind fields that haven't been allowed in initBinder(): "
							+ StringUtils.join(suppressedFields, ", "));
		}
	}
}
